/*
********************************************************************************
* Copyright (C) 2021, xiang.D <dx_65535@163.com>.
* All right reserved.
*
* File Name   : control_tower.cc
* Author      :
* Version     : V1.0
* Description :
* Journal     : 2021-1-20 version v1.0
* Brief       : Blog: https://blog.csdn.net/qq_38750572?spm=1001.2014.3001.5343
* Others      :
                Compile command: make
********************************************************************************
*/
#include <algorithm>
#include "airplane_base.h"
#include "control_tower.h"

using namespace std;

#define TOWER_LOGI(fmt, args...) printf(fmt, ##args)
#define TOWER_LOGD(fmt, args...) printf("%d Tower D: " fmt, __LINE__, ##args)
#define TOWER_LOGW(fmt, args...) printf("%d Tower W: " fmt, __LINE__, ##args)
#define TOWER_LOGE(fmt, args...) printf("%d Tower E: " fmt, __LINE__, ##args)

CChengduTowerMediator::CChengduTowerMediator()
{
    mAirplaneHashTable.clear();
}

CChengduTowerMediator::~CChengduTowerMediator()
{

}

CChengduTowerMediator* CChengduTowerMediator::GetInstance()
{
    static CChengduTowerMediator obj;
    return &obj;
}

// 注册, Tower分配Airplane通讯ID
int CChengduTowerMediator::Register(CAirplaneBase* airplane)
{
    int RegisterId = -1;
    map<int, CAirplaneBase*>::const_iterator it = mAirplaneHashTable.end();
    int i, maxIndex = -1;

    if (!airplane)
    {
        TOWER_LOGE("Register obj is NULL\n");
        return -1;
    }

    // hash表为空，分配Id 0
    if (it == mAirplaneHashTable.begin()) {
        //TOWER_LOGD("Table is empty!\n");
        RegisterId = 0;
        goto Ret;
    } else {
        it--;
    }

    maxIndex = it->first;
    for (i = 0; i <= maxIndex + 1; i++)
    {
        // 查询可用ID，分配给AirPlane
        // maxIndex + 1为空，必然能够获取到可用ID
        if (!mAirplaneHashTable[i]) {
            //TOWER_LOGD("table %d is null\n", i);
            RegisterId = i;
            break;
        }
    }

Ret:
    //TOWER_LOGD("Get Id %d max_id: %d\n", RegisterId, maxIndex);
    //mAirplaneHashTable.insert(RegisterId, airplane); // mAirplaneHashTable[1]为空，不清楚原因
    mAirplaneHashTable[RegisterId] = airplane;
    return RegisterId;
}

int CChengduTowerMediator::UnRegister(int RegisterId)
{
    if (!mAirplaneHashTable[RegisterId]) {
        TOWER_LOGE("Id %d is invalid!\n", RegisterId);
        return -1;
    }

    mAirplaneHashTable.erase(RegisterId);

    return RegisterId;
}

int CChengduTowerMediator::SendMsg(int RegisterId, void *msg)
{
    int ret = 0;

    if (!mAirplaneHashTable[RegisterId]) {
        TOWER_LOGE("Id %d is invalid!\n", RegisterId);
        return -1;
    }

    // TODO: 检测是否发送成功
    mAirplaneHashTable[RegisterId]->Receive(msg);

    return ret;
}

int CChengduTowerMediator::NotifyObserverAll(void *msg)
{
    int ret = 0;
    map<int, CAirplaneBase*>::const_iterator it;

    for (it = mAirplaneHashTable.begin(); it != mAirplaneHashTable.end(); it++) {
        if (!it->second) {
            TOWER_LOGW("Id %d is invalid!\n", it->first);
            continue;
        }

        // TODO: 检测是否发送成功
        it->second->Receive(msg);
    }

    return ret;
}

int CChengduTowerMediator::Receive(int id, void *msg)
{
    int ret = 0;

    TOWER_LOGI("Tower Recv: [%d] %s \n", id, (char *)msg);
    SendMsg(id, (char *)"Ack");

    return ret;
}
